package com.usoft;

import akka.dispatch.ExecutionContexts;
import akka.dispatch.Futures;
import akka.dispatch.Mapper;
import akka.dispatch.OnComplete;
import akka.dispatch.OnFailure;
import akka.dispatch.OnSuccess;
import scala.concurrent.ExecutionContextExecutorService;
import scala.concurrent.Future;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

/**
 * Created by liyanxin on 2015/1/8.
 */
public class FutureDemo {

    public static void main(String args[]) {

        // 执行上下文可以自己指定线程池类型
        // 需要一个ExecutionContext作为其executor
        // Future 需要一个ExecutionContext, 它与java.util.concurrent.Executor 很相像.
        // 如果你在作用域内有一个 ActorSystem , 它可以用system.dispatcher()作 ExecutionContext。
        // 你也可以用ExecutionContext
        // 伴生对象提供的工厂方法来将 Executors 和 ExecutorServices 进行包裹, 或者甚至创建自己的实例.
        ExecutionContextExecutorService ec = ExecutionContexts.
                fromExecutorService(Executors.newCachedThreadPool());

        Future<String> f1 = Futures.future(new Callable<String>() {
            public String call() throws InterruptedException {
                Thread.sleep(5000); //在当前的线程内阻塞5秒
                System.out.println(Thread.currentThread().getName() + " thread end|||f1");
                return "Hello" + "World";
            }
        }, ec);

        /**
         * 通过map方法 f1 -> f2
         * Now we have a second Future,
         * f2, that will eventually contain an Integer. When our original Future, f1, completes, it will also apply our
         * function and complete the second Future with its result. When we finally get the result, it will contain the
         * number 10. Our original Future still contains the string “HelloWorld” and is unaffected by the map.
         */
        Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
            public Integer apply(String s) {
                System.out.println(Thread.currentThread().getName() + " thread end|||f1->f2");
                return s.length();
            }
        }, ec);

        f2.onComplete(new OnComplete<Integer>() {
            @Override
            public void onComplete(Throwable failure, Integer success) throws Throwable {
                System.out.print(Thread.currentThread().getName() + " thread end|||");
                System.out.println("f2 on complete=" + success);
            }
        }, ec);

        f2.onSuccess(new OnSuccess<Integer>() {
            @Override
            public void onSuccess(Integer result) throws Throwable {
                System.out.print(Thread.currentThread().getName() + " thread end|||");
                System.out.println("返回结果的长度=" + result);
            }
        }, ec);

        f2.onFailure(new OnFailure() {
            @Override
            public void onFailure(Throwable failure) throws Throwable {
                System.out.print(Thread.currentThread().getName() + " thread end|||");
                System.out.println("f2 failure=" + failure.getMessage());
            }
        }, ec);
        System.out.println(Thread.currentThread().getName() + " thread end");
    }
}
